#include "recordset.h"
#include "stdafx.h"

CRecordSet::CRecordSet(sqlite3_stmt* pStmt3)
{
    std::map<unsigned int, std::string> mRecord;
    if (pStmt3 != NULL) {
        m_nFieldCount = sqlite3_column_count(pStmt3);
        for (unsigned int i = 0; i < m_nFieldCount; ++i) {
            int nColumnType = sqlite3_column_type(pStmt3, i);
            std::string strColumnName = sqlite3_column_name(pStmt3, i);
            m_vFieldIndex[strColumnName] = i;
        }
    }

    while (sqlite3_step(pStmt3) == SQLITE_ROW) {
        UINT uloop = 1;
        for (uloop = 1; uloop <= m_nFieldCount; uloop++) {
            char* pszValue = (char*)sqlite3_column_text(pStmt3, uloop - 1);
            mRecord[uloop] = pszValue;
        }
        m_vRecordList.push_back(mRecord);
    }

    m_nRowCount = m_vRecordList.size();
    m_nFieldCount = m_vFieldIndex.size();
    m_nRowPosition = 0;

    m_Record = m_vRecordList[0];
}

CRecordSet::~CRecordSet(void)
{
}

UINT CRecordSet::Next()
{
    if (m_nRowPosition == m_nRowCount) {
        m_nRowPosition++;
        return S_ERROR;
    } else if (m_nRowPosition < m_nRowCount + 1) {
        try {
            m_Record = m_vRecordList[m_nRowPosition];
            m_nRowPosition++;
            return S_SUCCESS;
        } catch (...) {
            return S_ERROR;
        }
    }

    return S_ERROR;
}

UINT CRecordSet::Previous()
{
    if (m_nRowPosition <= 0) {
        return S_ERROR;
    }
    m_nRowPosition--;
    try {
        m_Record = m_vRecordList[m_nRowPosition];
        return S_SUCCESS;
    } catch (...) {
        return S_ERROR;
    }
}

UINT CRecordSet::First()
{
    m_nRowPosition = 0;
    try {
        m_Record = m_vRecordList[m_nRowPosition];
        return S_SUCCESS;
    } catch (...) {
        return S_ERROR;
    }
}

UINT CRecordSet::Last()
{
    try {
        m_nRowPosition = m_nRowCount;
        m_Record = m_vRecordList[m_nRowPosition - 1];
        return S_SUCCESS;
    } catch (...) {
        return S_ERROR;
    }
}

unsigned int CRecordSet::GetFieldIndex(LPCSTR lpszName)
{
    std::map<std::string, unsigned int>::iterator it = m_vFieldIndex.find(lpszName);
    if (it != m_vFieldIndex.end()) {
        return it->second + 1;
    }
    return 0;
}

HRESULT CRecordSet::GetInt(LPCSTR lpszName, INT& nValue)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetInt(nIndex, nValue);
}

HRESULT CRecordSet::GetInt64(LPCSTR lpszName, int64& nValue)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetInt64(nIndex, nValue);
}

HRESULT CRecordSet::GetUInt(LPCSTR lpszName, UINT& nValue)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetUInt(nIndex, nValue);
}

HRESULT CRecordSet::GetUInt64(LPCSTR lpszName, uint64& nValue)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetUInt64(nIndex, nValue);
}

HRESULT CRecordSet::GetFloat(LPCSTR lpszName, float& fValue)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetFloat(nIndex, fValue);
}

HRESULT CRecordSet::GetDouble(LPCSTR lpszName, double& dValue)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetDouble(nIndex, dValue);
}

LPCSTR CRecordSet::GetString(LPCSTR lpszName)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetString(nIndex);
}

const unsigned char* CRecordSet::GetBlob(LPCSTR lpszName)
{
    unsigned int nIndex = GetFieldIndex(lpszName);
    return GetBlob(nIndex);
}

HRESULT CRecordSet::GetInt(unsigned int nIndex, INT& nValue)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return S_FALSE;
    }
    nValue = atoi(m_Record[nIndex].c_str());
    return S_OK;
}

HRESULT CRecordSet::GetInt64(unsigned int nIndex, int64& nValue)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return S_FALSE;
    }

    // nValue = _strtoi64(m_Record[nIndex].c_str(), NULL, 10);

    return S_OK;
}

HRESULT CRecordSet::GetUInt(unsigned int nIndex, UINT& nValue)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return S_FALSE;
    }
    uint64 iValue;

    GetUInt64(nIndex, iValue);
    nValue = static_cast<UINT>(iValue);
    return S_OK;
}

HRESULT CRecordSet::GetUInt64(unsigned int nIndex, uint64& nValue)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return S_FALSE;
    }

    // nValue = _strtoi64(m_Record[nIndex].c_str(), NULL, 10);

    return S_OK;
}

HRESULT CRecordSet::GetFloat(unsigned int nIndex, float& fValue)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return S_FALSE;
    }
    fValue = static_cast<float>(strtod(m_Record[nIndex].c_str(), NULL));
    return S_OK;
}

HRESULT CRecordSet::GetDouble(unsigned int nIndex, double& dValue)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return S_FALSE;
    }

    dValue = ::strtod(m_Record[nIndex].c_str(), NULL);

    return S_OK;
}

LPCSTR CRecordSet::GetString(unsigned int nIndex)
{
    if (nIndex <= 0 || nIndex > m_nFieldCount) {
        return NULL;
    }
    return m_Record[nIndex].c_str();
}

const unsigned char* CRecordSet::GetBlob(unsigned int nIndex)
{
    return (const unsigned char*)m_Record[nIndex].c_str();
}

HRESULT CRecordSet::CreateInstance(sqlite3_stmt* pStmt, IRecordSet** ppRecordSet)
{
    CRecordSet* p = ALLOC_NEW CRecordSet(pStmt);
    rc_error(p != NULL, E_FAIL);
    return p->QueryInterface(IID_IRecordSet, (void**)ppRecordSet);
}
